
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using WeChatWASM;

#if 微信小游戏
public class 微信自定义View : MonoBehaviour,I微信按钮
{
    //微信排行榜组件 是上下颠倒的；
    
    
    public float 延时检测;
    public bool 显示微信按钮位置;
    
    private Vector3 历史坐标;
    private Vector3 最新坐标;
    
    
    private Vector2 对象屏幕坐标;
    private Vector2 对象世界坐标;
    private Vector2 对象大小;
    private Canvas 画布;
    protected (int, int, int, int) 微信需要的坐标;//左 ，上， 宽， 高
    // protected (int, int, int, int) 微信需要的坐标_像素比;//左 ，上， 宽， 高
    private bool is初始化;

    [SerializeField]protected bool isShow;
    
    [SerializeField]private CanvasType selectedCanvasType;
    [SerializeField]private RawImage RankBody;//需要旋转180
    [SerializeField] private Vector3 画布大小 = new Vector3(1,-1,1);
    [SerializeField] private Transform View模型;
    private WXOpenDataContext openDataContext;



    [ContextMenu("测试修改坐标")]
    public void Test修改坐标()
    {
        var rect = View模型.GetComponent<RectTransform>();
        自定义布局 b = 转自定义布局(rect, true);
        Dictionary<string, HtmlStyle> style = 转HtmlStyles(rect);
        
        OpenDataMessage msgData = new OpenDataMessage();
        msgData.type = 开放域处理类型.show自定义.ToString();
        msgData.Data = new Dictionary<string, object>();
        msgData.Data.Add("Style",style);
        msgData.Data.Add("布局",new List<自定义布局>(){b});
        
        Debug.Log(JsonConvert.SerializeObject(msgData));
    }

    private 自定义布局 转自定义布局(RectTransform rect, bool isFater)
    {
        自定义布局 res = new 自定义布局();
        if (isFater)
        {
            res.id = "main";//应该是固定的
        }
        res.StyleName = rect.name;
        string type = HtmlViewType.view.ToString();
        string param = "";

        Text text = rect.GetComponent<Text>();
        if (text != null)
        {
            type = HtmlViewType.text.ToString();
            param = text.text;
        }
        else
        {
            RawImage raw = rect.GetComponent<RawImage>();
            if (raw != null)
            {
                type = HtmlViewType.image.ToString();
                string 图片固定前缀 = "open-data/render/image/";
                string 图片名字="";
                图片名字 = raw.texture.name;
                param = 图片固定前缀 + 图片名字+".png";
            }
            // Image im = rect.GetComponent<Image>();//TODO 开放域默认的图片是Texture
        }
        
        res.type = type;
        res.param = param;
        if (rect.childCount > 0)
        {
            res.Children = new List<自定义布局>();
            for (int i = 0; i < rect.childCount; i++)
            {
                var r = rect.GetChild(i).GetComponent<RectTransform>();
                自定义布局 child = 转自定义布局(r, false);
                res.Children.Add(child);
            }
        }

        return res;
    }
    public static List<T> 递归执行Tranform<T>( Transform tran ,Func<Transform,T> 处理)
    {
        List<T> res = new List<T>();
        处理递归(tran, ref res);
        

        void 处理递归(Transform tr, ref List<T> r)
        {
            if (r == null)
            {
                r = new List<T>();
            }

            T get = 处理.Invoke(tr);
            r.Add(get);
            if (tr.childCount > 0)
            {
                for (int i = 0; i < tr.childCount; i++)
                {
                    处理递归(tr.GetChild(i), ref r);
                }
            }
        }

        return res;
    }

    ///重复名字的只记录第一个，请区分命名
    private Dictionary<string, HtmlStyle> 转HtmlStyles(RectTransform rect)
    {
        // rect.修改锚点( M.AnchorType.TopLeft,new Vector2(0,1));
        //统一 top + left 计算
        float f = 画布比例;
        Dictionary<string, HtmlStyle> 结果 = new Dictionary<string, HtmlStyle>();

        List <(string,HtmlStyle)> allStyle= 递归执行Tranform(rect.transform,(t) =>
        {
            RectTransform r = t.GetComponent<RectTransform>();
            // if (r.检查锚点() != M.AnchorType.TopLeft)
            // {
            //     Debug.LogError("请设置锚点左上==========="+t.name);
            // }
            HtmlStyle s = new HtmlStyle();
            Vector2 pos = r.anchoredPosition;
            Vector2 size = r.sizeDelta;
            s.top = (int)(pos.y*-1*画布比例);
            s.left = (int)(pos.x*画布比例);
            s.width = (int)(size.x*画布比例);
            s.height = (int)(size.y*画布比例);
            return (t.name,s);
        });

        foreach (var VARIABLE in allStyle)
        {
            if (!结果.ContainsKey(VARIABLE.Item1))
            {
                结果.Add(VARIABLE.Item1,VARIABLE.Item2);
            }
        }

        return 结果;
    }


    protected bool cur按钮状态;
    public bool IsShow
    {
        get { return isShow; }
        set
        {
            if (isShow != value)
            {
                isShow = value;
                if (isShow)
                {
                    if (!is初始化)
                    {
                        Awake();
                    }
                    Show按钮();
                }
                else
                {
                    Hide按钮();
                }
            }
        }
    }

    // private void OnDestroy()
    // {
    //     Hide按钮();
    // }

    private void OnDisable()
    {
        Hide按钮();
    }

    private void OnEnable()
    {
        cur延迟 = 0f;
    }

    private bool 平稳后坐标修改;
    protected virtual void 坐标修改()
    {
        // if(该按钮会移动_开启及时检测)
        if (cur按钮状态)
        {
            // Hide按钮();
            Show按钮();
        }
    }

    private void Awake()
    {
        // 一次计算；
        画布 = transform.GetComponentInParent<Canvas>();
        var rect = transform.GetComponent<RectTransform>();
        var prePivot = rect.pivot;
        var prePos = rect.anchoredPosition;
        var size = rect.sizeDelta;
        rect.pivot = new Vector2(0.5f, 0.5f);//坐标锚点 改成左上角；

        var 相对自私点 = rect.pivot - prePivot;
        rect.anchoredPosition = prePos + 相对自私点 * size;
        
        对象大小 = rect.sizeDelta;
        rect.transform.localScale = 画布大小;
        
        计算坐标();

        历史坐标 = transform.position;
        最新坐标 = 历史坐标;
    }
    

    private Rect guiRect;
    private GUIContent infoContent;
    private void OnGUI()
    {
        if (显示微信按钮位置 && cur按钮状态)
        {
            GUI.Button(guiRect,infoContent); 
        }
    }

    void 计算坐标()
    {
        计算对象屏幕坐标();
        计算微信需要坐标();
        is初始化 = true;
    }
    public void 重新计算坐标()
    {
        计算坐标();
    }

    void 计算对象屏幕坐标()
    {
        对象世界坐标 = transform.position;
        
        RenderMode 画布RenderMode = 画布.renderMode;
        //TODO 分类计算屏幕坐标；
        switch (画布RenderMode)
        {
            case RenderMode.ScreenSpaceOverlay:
                // 对象屏幕坐标 = 对象世界坐标
                break;
            default:
                Debug.LogError("其他画布渲染坐标可能不对！！");
                break;
        }
        
        
    }

    private float 画布比例 = 1f;
    void 计算微信需要坐标()
    {
        
        
        CanvasScaler scaler = 画布.GetComponent<CanvasScaler>();
        var referenceResolution = scaler.referenceResolution;
        画布比例 = (Screen.width / referenceResolution.x);
        float f = 画布比例;
        
        //==============================================================================================================
        对象屏幕坐标 = (Vector2)对象世界坐标 + (对象大小*new Vector2(-0.5f,0.5f)*f);
        // var size = ;
        // Vector2 Canvas坐标_Z0 = new Vector2(Screen.width / 2f, Screen.height / 2f);
        // int 方向 = 1;
        Debug.Log(对象屏幕坐标);
        
        int x = (int) 对象屏幕坐标.x;
        int y = (int) (Screen.height-对象屏幕坐标.y);
        int width = (int)对象大小.x;
        int hegiht = (int)对象大小.y;
        
        // float f2 = (Screen.height / referenceResolution.y);
        int 比例width = (int) (width * f);
        int 比例hegiht = (int) (hegiht * f);

        微信需要的坐标 = (x, y, 比例width, 比例hegiht);
        Debug.Log("微信需要的坐标：：");
        Debug.Log(微信需要的坐标);

        // float 像素比 = 1f;
// #if !UNITY_EDITOR
//         像素比 = WeiChatSDK.微信SDK.系统信息.pixelRatio;
// #endif
//         int 屏幕x = (int) (对象屏幕坐标.x/像素比);
//         int 屏幕y = (int) ((Screen.height-对象屏幕坐标.y)/像素比);
//         int 屏幕width = (int) (比例width/像素比);
//         int 屏幕hegiht = (int) (比例hegiht/像素比);
//         微信需要的坐标_像素比= (屏幕x, 屏幕y, 屏幕width, 屏幕hegiht);

        if (显示微信按钮位置)
        {
            var guipos = new Vector2(x, y);
            var size = new Vector2(比例width, 比例hegiht);
            guiRect = new Rect(guipos, size);
            infoContent = new GUIContent();
        }
    }

    [ContextMenu("Test遮挡")]
    public void Test遮挡()
    {
        遮挡判断();
    }

    private float cur延迟 = 0f;
    private void Update()
    {
        if (isShow)
        {
            bool is遮挡 = 遮挡判断();
            if (is遮挡 && cur按钮状态)
            {
                Hide按钮();
            }
            else if(!is遮挡 && !cur按钮状态)
            {
                Show按钮();
            }
            
            
            // if (该按钮会移动_开启及时检测)
            // {
            //     最新坐标 = transform.position;
            //     if (最新坐标 != 历史坐标)
            //     {
            //         对象移动_坐标变更(最新坐标);
            //         历史坐标 = 最新坐标;
            //         平稳后坐标修改 = true;
            //     }else if (平稳后坐标修改)
            //     {
            //         平稳后坐标修改 = false;
            //         坐标修改();
            //     }
            // }
        }

        if (延时检测 > 0f && cur延迟<延时检测)
        {
            cur延迟 += Time.deltaTime;
            if (cur延迟 >= 延时检测)
            {
                计算坐标();
                坐标修改();
            }
        }
    }

    void 对象移动_坐标变更(Vector3 v3)
    {
        计算坐标();
    }


    public bool 遮挡判断()
    {
        PointerEventData 点击事件 = new PointerEventData(EventSystem.current);
        点击事件.position = 对象世界坐标; 
        GraphicRaycaster UI光线投射器 = 画布.GetComponent<GraphicRaycaster>();
        List<RaycastResult> 结果 = new List<RaycastResult>();
        UI光线投射器.Raycast(点击事件, 结果);

        if (结果.Count <= 0)
        {
            return false;
        }
        
        if (结果[0].gameObject == gameObject || 结果[0].gameObject.transform.IsChildOf(transform))
        {
            return false;
        }

        // Debug.Log("判断有遮挡，遮挡物="+结果[0].gameObject);
        return true;
    }

    // public virtual void 创建按钮()
    // {
    // }

    protected virtual void Show按钮()
    {
        cur按钮状态 = true;
        
// #if UNITY_EDITOR
//         return;
// #endif

        if (openDataContext == null)
        {
            openDataContext = new WXOpenDataContext(new OpenDataContextOption(){sharedCanvasMode = selectedCanvasType});
        }
        Debug.Log("微信需要的坐标="+微信需要的坐标);
        
        var size = 微信需要的坐标;
        WX.ShowOpenData(RankBody.texture,size.Item1,size.Item2,size.Item3,size.Item4);
        
        var rect = View模型.GetComponent<RectTransform>();
        自定义布局 b = 转自定义布局(rect, true);
        Dictionary<string, HtmlStyle> style = 转HtmlStyles(rect);
        
        OpenDataMessage msgData = new OpenDataMessage();
        msgData.type = 开放域处理类型.show自定义.ToString();
        msgData.Data = new Dictionary<string, object>();
        msgData.Data.Add("Style",style);
        msgData.Data.Add("布局",new List<自定义布局>(){b});
        
        string msg = JsonConvert.SerializeObject(msgData);
        Debug.Log(msg);
        openDataContext.PostMessage(msg);
    }

    private Dictionary<string, object> callback(string s,Action<string> ac)
    {
        Dictionary<string, object> mmm = new Dictionary<string, object>();
        mmm.Add("hellp","moqii");
        // mmm.Add("hellp2",ac);
        return mmm;
    }
    protected virtual void Hide按钮()
    {
        cur按钮状态 = false;
        WX.HideOpenData();
    }

    public void Show按钮公共()
    {
        IsShow = true;
    }

    public void Hide按钮公共()
    {
        IsShow = false;
    }
}


public enum 开放域处理类型
{
    showFriendsRank,
    show自定义,
    
}

[Serializable]
public class TestStyle
{
    public HtmlStyle test1;
    public HtmlStyle test2;
}

[Serializable]
public class HtmlStyle
{
    public int top;
    public int left;
    // public int right;
    // public int bottom;
    public int width;
    public int height;
    public string position = "absolute";
}

[Serializable]
public class 自定义布局
{
    public string StyleName;
    public string type;
    public string param;
    public string id;
    
    public List<自定义布局> Children;
}

public enum HtmlViewType
{
    view,
    image,
    text,
}


#endif

